package com.funny.stock.trade.controller;

import com.funny.stock.base.util.PropertiesCopyUtil;
import com.funny.stock.base.util.ResultUtil;
import com.funny.stock.base.vo.Result;
import com.funny.stock.base.vo.TradeType;
import com.funny.stock.data.collect.impl.RealTimeStockServiceDelegate;
import com.funny.stock.data.vo.RealtimeStockData;
import com.funny.stock.data.vo.StockConstants;
import com.funny.stock.data.vo.StockType;
import com.funny.stock.trade.dao.pojo.ComposeStockItemDO;
import com.funny.stock.trade.dao.pojo.DayTradeProfitDO;
import com.funny.stock.trade.dao.pojo.DayTradeRecordDO;
import com.funny.stock.trade.dao.pojo.GridTradePlanVarDO;
import com.funny.stock.trade.service.ComposeStockItemService;
import com.funny.stock.trade.service.DayTradeProfitService;
import com.funny.stock.trade.service.DayTradeRecordService;
import com.funny.stock.trade.service.GridTradePlanService;
import com.funny.stock.trade.service.GridTradePlanVarService;
import com.funny.stock.trade.vo.ComposeTradeProfitVO;
import com.funny.stock.trade.vo.DayTradeProfitVO;
import com.funny.stock.trade.vo.DayTradeRecordVO;
import com.funny.stock.trade.vo.GridTradePlanDetailVO;
import com.funny.stock.trade.vo.GridTradePlanListVO;
import com.funny.stock.trade.vo.GridTradePlanVO;
import com.funny.stock.user.util.UserSecurityUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author pengl
 * @date 2020/05/17
 **/
@RestController
@RequestMapping("/stock/tradePlan/grid")
public class GridTradePlanController {
    public static final Logger logger = LoggerFactory.getLogger(GridTradePlanController.class);

    @Autowired
    GridTradePlanService tradePlanService;

    @Autowired
    GridTradePlanVarService gridTradePlanVarService;

    @Autowired
    ComposeStockItemService stockItemService;

    @Autowired
    RealTimeStockServiceDelegate realTimeStockServiceDelegate;

    @Autowired
    DayTradeRecordService dayTradeRecordService;

    @Autowired
    DayTradeProfitService dayTradeProfitService;

    @GetMapping("/list")
    public Result list(@RequestParam Long composeId){
        Long userId = UserSecurityUtil.getUserId();
        List<GridTradePlanVO> gridTradePlanDOS = tradePlanService.queryTradePlanList(userId.intValue(),composeId);

        if(CollectionUtils.isEmpty(gridTradePlanDOS))
            return ResultUtil.success(null);

        Map<String,Object> dataMap = new HashMap<>();
        List<GridTradePlanListVO> vos = PropertiesCopyUtil.copyPropertiesByList(gridTradePlanDOS, GridTradePlanListVO.class);
        Map<Long, ComposeTradeProfitVO> profitVOMap = dayTradeRecordService.queryComposeTradeProfitMap(userId, composeId, StockConstants.STOCK_STRATEGY_GRID);
        BigDecimal sumProfit = BigDecimal.ZERO;
//        if(!CollectionUtils.isEmpty(profitVOMap)) {
            for (GridTradePlanListVO listVO : vos) {
                ComposeTradeProfitVO profitVO = profitVOMap.get(listVO.getId());
                if(profitVO == null) {
                    listVO.setProfitMoney(BigDecimal.ZERO);
                    listVO.setProfitNumber(0L);
                    continue;
                }
                listVO.setProfitMoney(profitVO.getProfitMoney());
                listVO.setProfitNumber(profitVO.getProfitNumber());
                sumProfit = sumProfit.add(profitVO.getProfitMoney());
            }
//        }
        dataMap.put("content",vos);
        dataMap.put("summaryProfit",sumProfit.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
        return ResultUtil.success(dataMap);
    }

    @GetMapping("/detail/{id}")
    public Result<GridTradePlanDetailVO> detail(@PathVariable Long id){
        Long userId = UserSecurityUtil.getUserId();
        GridTradePlanVO planDO = tradePlanService.findByIdAndCreateId(id, userId);
        if(planDO == null) return ResultUtil.error("不存在的计划");

        GridTradePlanDetailVO detailVO = new GridTradePlanDetailVO();
        GridTradePlanVO gridTradePlanVO = PropertiesCopyUtil.copyProperties(planDO, GridTradePlanVO.class);
        detailVO.setPlanData(gridTradePlanVO);
        detailVO.setStockName(gridTradePlanVO.getStockName());
        detailVO.setStockCode(gridTradePlanVO.getStockCode());

        GridTradePlanVarDO tradePlanVarDO = gridTradePlanVarService.findByPlanId(planDO.getId());
        if(tradePlanVarDO != null){
            detailVO.setNextBuyPrice(tradePlanVarDO.getNextBuyPrice());
            detailVO.setNextSellPrice(tradePlanVarDO.getNextSellPrice());
        }

        ComposeStockItemDO stockItemDO = stockItemService.queryStockItem(userId, planDO.getComposeId(), planDO.getStockCode());
        if(stockItemDO != null){
            detailVO.setStockNumber(stockItemDO.getStockNumber());

            RealtimeStockData realtimeData = realTimeStockServiceDelegate.getRealtimeData(stockItemDO.getStockCode(),
                    StockType.getValueByType(stockItemDO.getStockMarket()));
            if(realtimeData != null){
                detailVO.setPrice(realtimeData.getPrice());
                detailVO.setUpdown(realtimeData.getUpdown());
                BigDecimal percent = BigDecimal.valueOf(realtimeData.getPercent()).multiply(BigDecimal.valueOf(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                detailVO.setPercent(percent);
            }
        }

        DayTradeRecordDO recordDO = new DayTradeRecordDO();
        recordDO.setUserId(userId);
        recordDO.setPlanType(StockConstants.STOCK_STRATEGY_GRID);
        recordDO.setComposeId(planDO.getComposeId());
        recordDO.setStockCode(gridTradePlanVO.getStockCode());

        Page<DayTradeRecordDO> page = dayTradeRecordService.queryByCondition(recordDO, 0, Integer.MAX_VALUE);
        List<DayTradeRecordVO> recordVOList = PropertiesCopyUtil.copyPropertiesByList(page.getContent(),DayTradeRecordVO.class);

        List<DayTradeProfitDO> profitDOList = dayTradeProfitService.findTradeProfitList(planDO.getComposeId(), StockConstants.STOCK_STRATEGY_GRID, userId);
        List<DayTradeProfitVO> profitVOS = PropertiesCopyUtil.copyPropertiesByList(profitDOList, DayTradeProfitVO.class);
        if(!CollectionUtils.isEmpty(profitVOS)){
            Map<Long, DayTradeRecordVO> recordMap = recordVOList.stream().collect(Collectors.toMap(DayTradeRecordVO::getId, Function.identity(), (k1, k2) -> k2));

            for (DayTradeProfitVO profitVO : profitVOS) {
                DayTradeRecordVO buyRecordVO = recordMap.get(profitVO.getBuyTradeId());
                DayTradeRecordVO sellRecordVO = recordMap.get(profitVO.getSellTradeId());
                profitVO.setSellTradeVO(sellRecordVO);
                profitVO.setBuyTradeVO(buyRecordVO);
            }
        }

        detailVO.setBuyNumber(0L);
        detailVO.setSellNumber(0L);
        if(!CollectionUtils.isEmpty(recordVOList)){
            long buyNumber = 0,sellNumber = 0;
            for (DayTradeRecordVO item : recordVOList) {
                if(item.getType() == TradeType.BUY.getType()){
                    buyNumber++;
                }else{
                    sellNumber++;
                }
            }
            detailVO.setBuyNumber(buyNumber);
            detailVO.setSellNumber(sellNumber);
        }

        detailVO.setTradeRecordList(recordVOList);
        detailVO.setTradeProfitList(profitVOS);

        return ResultUtil.success(detailVO);
    }


    @GetMapping("/queryTradeRecordByPage")
    public Result recordList(@RequestParam Long planId,
                             @RequestParam String code,
                             @RequestParam(required = false) Integer pageNumber,
                             @RequestParam(required = false) Integer pageSize){
//        Long userId = UserSecurityUtil.getUserId();
//        PageRequest pageRequest = PageUtil.buildPageRequest(pageNumber, pageSize);
//        Page<DayTradeRecordDO> page = dayTradeRecordService.findByPlanIdAndStockCodeAndPlanType(planId, code, StockConstants.STOCK_STRATEGY_T0, pageRequest);
//        return ResultUtil.success(page);
        return ResultUtil.success(null);
    }


    @PostMapping("/save")
    public Result savePlan(@RequestBody GridTradePlanVO dataObj){
        Long userId = UserSecurityUtil.getUserId();
        if(dataObj.getComposeId() == null)
            return ResultUtil.error("模拟组合ID为空");

        if(dataObj.getStockCode() == null)
            return ResultUtil.error("成交股票代码为空");

        if(dataObj.getStockName() == null)
            return ResultUtil.error("成交股票名称为空");

        if(dataObj.getBasePrice() == null)
            return ResultUtil.error("基准价为空");

        if(dataObj.getTradeStockNum() == null)
            return ResultUtil.error("每笔交易数量为空");

        if(dataObj.getIncreasePer() == null || dataObj.getDecreasePer() == null)
            return ResultUtil.error("涨幅或跌幅为空");

//        if(dataObj.getBuyLockType() == null || dataObj.getSellLockType() == null)
//            return ResultUtil.error("买入或卖出锁定类型为空");
//
//        if(dataObj.getTrustPrice() == null)
//            return ResultUtil.error("委托价类型为空");
        //todo 其他参数校验
        //检查是否持仓该股票

        if(dataObj.getId() == null) {
            dataObj.setCreateId(userId);
            dataObj.setCreateTime(new Date());
        }else{
            dataObj.setUpdateId(userId);
            dataObj.setUpdateTime(new Date());
        }

//        GridTradePlanDO gridTradePlanDO = PropertiesCopyUtil.copyProperties(dataObj, GridTradePlanDO.class);
        return ResultUtil.success( tradePlanService.add(dataObj));
    }

    @PostMapping("/start/{id}")
    public Result startPlan(@PathVariable Long id){
        Long userId = UserSecurityUtil.getUserId();
        GridTradePlanVO gridTradePlanDO = tradePlanService.startPlan(id, userId.intValue());
        if(gridTradePlanDO == null) return ResultUtil.error("启动计划失败");

        return ResultUtil.success("启动计划成功");
    }

    @PostMapping("/stop/{id}")
    public Result stopPlan(@PathVariable Long id){
        Long userId = UserSecurityUtil.getUserId();
        GridTradePlanVO gridTradePlanDO = tradePlanService.stopPlan(id, userId.intValue());
        if(gridTradePlanDO == null) return ResultUtil.error("停止计划失败");
        return ResultUtil.success("停止计划成功");
    }

    @PostMapping("/delete/{id}")
    public Result deletePlan(@PathVariable Long id){
        Long userId = UserSecurityUtil.getUserId();
        GridTradePlanVO gridTradePlanDO = tradePlanService.remove(id, userId.intValue());
        if(gridTradePlanDO == null) return ResultUtil.error("删除计划失败");
        return ResultUtil.success("删除计划失败");
    }

//    @Autowired
//    GridTradeMonitorService gridTradeMonitorService;
//
//    @GetMapping("/test")
//    public Result test(){
//        String json = "{\"code\":\"600036\",\"personId\":3,\"composeId\":8,\"planId\":3,\"planType\":\"grid\",\"realtimeStockData\":{\"arrow\":\"↑\",\"ask1\":45.13,\"ask2\":45.2,\"ask3\":45.21,\"ask4\":45.24,\"ask5\":45.25,\"askvol1\":2000,\"askvol2\":700,\"askvol3\":900,\"askvol4\":2400,\"askvol5\":6500,\"bid1\":45.12,\"bid2\":45.11,\"bid3\":45.1,\"bid4\":45.09,\"bid5\":45.08,\"bidvol1\":1200,\"bidvol2\":30700,\"bidvol3\":14300,\"bidvol4\":17003,\"bidvol5\":2800,\"code\":\"0600036\",\"high\":45.49,\"low\":45.09,\"name\":\"招商银行\",\"open\":45.4,\"percent\":8.87E-4,\"price\":45.13,\"status\":0,\"symbol\":\"600036\",\"time\":\"2020/11/27 09:45:55\",\"turnover\":242108186,\"type\":\"SH\",\"update\":\"2020/11/27 09:45:55\",\"updown\":0.04,\"volume\":5345583,\"yestclose\":45.09},\"tradeNumber\":400,\"tradeType\":\"SELL\"}\n";
//        MonitorActionInfo actionInfo = JSON.parseObject(json, MonitorActionInfo.class);
//        List<GridTradePlanDO> planDOS = tradePlanService.queryTradingPlanList();
//        if(planDOS.size() != 0) {
//            GridTradePlanDO planDO = planDOS.get(0);
//            gridTradeMonitorService.doTradeAction(actionInfo.getRealtimeStockData(),planDO,true);
//        }
//        return ResultUtil.success(null);
//    }

}
